package main

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"log"
	"net"
	"time"
)

const (
	FrameHeader = 0xA55A
	FrameTail   = 0xCC33C33C
)

type Frame struct {
	Header       uint16
	Length       uint8
	Manufacturer uint8
	Version      uint8
	FrameType    uint8
	DeviceID     [4]byte
	Info         []byte
	Checksum     uint8
	Tail         uint32
}

type DeviceAttributes struct {
	SIMCard          string
	GroupID          uint16
	TowerInGroup     uint16
	RopeRate         uint8
	XCoordinate      float32
	YCoordinate      float32
	FrontArmLength   float32
	RearArmLength    float32
	TowerCapHeight   float32
	TowerBodyHeight  float32
	Longitude        float64
	Latitude         float64
	MaxLeftAngle     float32
	MaxRightAngle    float32
	MaxFrontDistance float32
	MaxRearDistance  float32
	MaxHeight        float32
	MaxWeight        float32
	WarningRate      uint8
	AlarmRate        uint8
	ViolationRate    uint8
}

func parseFrame(data []byte) (*Frame, error) {
	if len(data) < 14 { // Minimum frame length
		return nil, fmt.Errorf("数据太短")
	}

	header := binary.BigEndian.Uint16(data[0:2])
	if header != FrameHeader {
		return nil, fmt.Errorf("无效的帧头: %x", header)
	}

	length := data[2]
	expectedLength := int(length) // Length includes the entire frame length
	if len(data) != expectedLength {
		return nil, fmt.Errorf("无效的数据长度: 期望 %d, 实际 %d", expectedLength, len(data))
	}

	tail := binary.BigEndian.Uint32(data[len(data)-4:])
	if tail != FrameTail {
		return nil, fmt.Errorf("无效的帧尾: %x", tail)
	}

	frame := &Frame{
		Header:       header,
		Length:       length,
		Manufacturer: data[3],
		Version:      data[4],
		FrameType:    data[5],
	}
	copy(frame.DeviceID[:], data[6:10])
	frame.Info = data[10 : len(data)-5]
	frame.Checksum = data[len(data)-5]
	frame.Tail = tail

	return frame, nil
}

func parseTimestamp(info []byte) (time.Time, error) {
	if len(info) < 4 {
		return time.Time{}, fmt.Errorf("信息段太短，无法解析时间戳")
	}
	timestamp := binary.BigEndian.Uint32(info[:4])
	return time.Unix(int64(timestamp), 0), nil
}

func parseDeviceAttributes(info []byte) (*DeviceAttributes, error) {
	if len(info) < 88 {
		return nil, fmt.Errorf("信息段太短，无法解析设备属性")
	}

	attributes := &DeviceAttributes{
		SIMCard:          string(info[:20]),
		GroupID:          binary.BigEndian.Uint16(info[20:22]),
		TowerInGroup:     binary.BigEndian.Uint16(info[22:24]),
		RopeRate:         info[24],
		XCoordinate:      float32(binary.BigEndian.Uint32(info[25:29])) / 100,
		YCoordinate:      float32(binary.BigEndian.Uint32(info[29:33])) / 100,
		FrontArmLength:   float32(binary.BigEndian.Uint32(info[33:37])) / 100,
		RearArmLength:    float32(binary.BigEndian.Uint32(info[37:41])) / 100,
		TowerCapHeight:   float32(binary.BigEndian.Uint32(info[41:45])) / 100,
		TowerBodyHeight:  float32(binary.BigEndian.Uint32(info[45:49])) / 100,
		Longitude:        float64(binary.BigEndian.Uint32(info[49:53])) / 1000000,
		Latitude:         float64(binary.BigEndian.Uint32(info[53:57])) / 1000000,
		MaxLeftAngle:     float32(binary.BigEndian.Uint32(info[57:61])) / 100,
		MaxRightAngle:    float32(binary.BigEndian.Uint32(info[61:65])) / 100,
		MaxFrontDistance: float32(binary.BigEndian.Uint32(info[65:69])) / 100,
		MaxRearDistance:  float32(binary.BigEndian.Uint32(info[69:73])) / 100,
		MaxHeight:        float32(binary.BigEndian.Uint32(info[73:77])) / 100,
		MaxWeight:        float32(binary.BigEndian.Uint32(info[77:81])) / 100,
		WarningRate:      info[81],
		AlarmRate:        info[82],
		ViolationRate:    info[83],
	}

	return attributes, nil
}

func handleClient(conn net.Conn) {
	defer conn.Close()

	for {
		// 从客户端读取数据
		buffer := make([]byte, 1024)
		n, err := conn.Read(buffer)
		if err != nil {
			log.Println("读取数据失败:", err)
			break
		}

		// 输出从客户端接收到的数据
		fmt.Printf("收到客户端数据: %s\n", hex.EncodeToString(buffer[:n]))

		// 解析数据
		frame, err := parseFrame(buffer[:n])
		if err != nil {
			log.Println("解析数据失败:", err)
			continue
		}

		// 打印解析后的数据
		fmt.Printf("解析后的数据帧: %+v\n", frame)
		fmt.Printf("帧头: 0x%x\n", frame.Header)
		fmt.Printf("长度: %d\n", frame.Length)
		fmt.Printf("厂家编号: 0x%x\n", frame.Manufacturer)
		fmt.Printf("协议版本: 0x%x\n", frame.Version)
		fmt.Printf("帧类型: 0x%x\n", frame.FrameType)
		fmt.Printf("设备编号: 0x%x\n", frame.DeviceID)
		fmt.Printf("信息段: 0x%x\n", frame.Info)
		fmt.Printf("校验和: 0x%x\n", frame.Checksum)
		fmt.Printf("帧尾: 0x%x\n", frame.Tail)

		// 解析信息段中的时间戳
		timestamp, err := parseTimestamp(frame.Info)
		if err != nil {
			log.Println("解析时间戳失败:", err)
			continue
		}
		fmt.Printf("解析的时间戳: %s\n", timestamp.Format(time.RFC3339))

		// 解析设备属性信息
		if frame.FrameType == 0x02 {
			attributes, err := parseDeviceAttributes(frame.Info)
			if err != nil {
				log.Println("解析设备属性信息失败:", err)
				continue
			}

			fmt.Printf("解析的设备属性信息: %+v\n", attributes)
			fmt.Printf("SIM卡号: %s\n", attributes.SIMCard)
			fmt.Printf("群塔ID: %d\n", attributes.GroupID)
			fmt.Printf("塔机在群: %d\n", attributes.TowerInGroup)
			fmt.Printf("吊绳倍率: %d\n", attributes.RopeRate)
			fmt.Printf("X坐标: %.2f\n", attributes.XCoordinate)
			fmt.Printf("Y坐标: %.2f\n", attributes.YCoordinate)
			fmt.Printf("前臂长度: %.2f\n", attributes.FrontArmLength)
			fmt.Printf("后臂长度: %.2f\n", attributes.RearArmLength)
			fmt.Printf("塔帽高度: %.2f\n", attributes.TowerCapHeight)
			fmt.Printf("塔身高度: %.2f\n", attributes.TowerBodyHeight)
			fmt.Printf("经度: %.6f\n", attributes.Longitude)
			fmt.Printf("纬度: %.6f\n", attributes.Latitude)
			fmt.Printf("左转最大角度: %.2f\n", attributes.MaxLeftAngle)
			fmt.Printf("右转最大角度: %.2f\n", attributes.MaxRightAngle)
			fmt.Printf("前行最远距离: %.2f\n", attributes.MaxFrontDistance)
			fmt.Printf("回收最近距离: %.2f\n", attributes.MaxRearDistance)
			fmt.Printf("最高高度: %.2f\n", attributes.MaxHeight)
			fmt.Printf("最大起重量: %.2f\n", attributes.MaxWeight)
			fmt.Printf("预警百分比: %d\n", attributes.WarningRate)
			fmt.Printf("报警百分比: %d\n", attributes.AlarmRate)
			fmt.Printf("违章百分比: %d\n", attributes.ViolationRate)
		}

		// 将接收到的数据发送回客户端
		_, err = conn.Write(buffer[:n])
		if err != nil {
			log.Println("发送数据失败:", err)
			break
		}
	}
}

func main() {
	// 设置服务器监听的地址和
	// 设置服务器监听的地址和端口
	listener, err := net.Listen("tcp", ":5050")
	if err != nil {
		log.Fatal("监听失败:", err)
	}
	defer listener.Close()

	fmt.Println("服务器启动，监听 5050 端口...")

	// 接受连接
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("接受连接失败:", err)
			continue
		}

		// 为每个连接创建一个 goroutine 来处理
		go handleClient(conn)
	}
}
